package com.zhou.copyjar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.zhou.copyjar.ManifestDependencyParser.parseManifestDependencies;

/**
 * @author zhoulj(1217102780 @ qq.com)
 * @version 2.0.0
 * @description:
 * @date 2025/7/17 14:32
 */
public class CopyJarV2 {
    static void copy(String jarPath, String srcPathStr, String desPathStr) {
        //获取源文件的名称
        try {
            File srcFile = new File(srcPathStr);
            if (!srcFile.exists()) {
                System.err.println("项目："+jarPath+"缺失jar 文件：" + srcPathStr);
            }
            FileInputStream fis = new FileInputStream(srcPathStr);//创建输入流对象
            File desFile = new File(desPathStr);
            File parentFile = desFile.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            desFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(desPathStr); //创建输出流对象
            byte datas[] = new byte[1024 * 1];//创建搬运工具
            int len = 0;//创建长度
            while ((len = fis.read(datas)) != -1)//循环读取数据
            {
                fos.write(datas, 0, len);
            }
            fis.close();//释放资源
            fis.close();//释放资源
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static List<Path> findJarFiles(String  handlePath) {
        Path currentDir = Paths.get(handlePath);

        // 1. 当前目录有conf 文件夹
        // 2. 当前目录没有lib 文件夹加
        // 3. 该jar 有main.class
        try {
            // 查找所有 JAR 文件
            List<Path> jarFiles = Files.walk(currentDir)
                    .filter(path ->
                            Files.isRegularFile(path) &&
                                    path.getFileName().toString().toLowerCase().endsWith(".jar") &&
                                    !path.getFileName().toString().toLowerCase().contains("copyjar")
                    )
                    .map(Path::normalize)
                    .toList();
            List<Path> config = jarFiles.stream().filter(path -> {
                boolean hasConfigDir = Files.exists(path.getParent().resolve("conf")) ;
                /*try {
                    hasConfigDir = Files.exists(path.getParent().resolve("conf"))
                    && (!Files.exists(path.getParent().resolve("lib"))
                            || Files.list(path.getParent().resolve("lib")).count()>0);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }*/
                return hasConfigDir;
            }).collect(Collectors.toList());
            List<Path> jarPath = config.stream().filter(path -> {
                try {
                    JarFile jarFile = new JarFile(path.toFile());
                    Manifest manifest = jarFile.getManifest();
                    if (manifest == null) {
                        return false;
                    }

                    Attributes mainAttributes = manifest.getMainAttributes();
                    if (mainAttributes == null) {
                        return false;
                    }
                    String mainClass = mainAttributes.getValue(Attributes.Name.MAIN_CLASS);
                    if (mainClass != null && !mainClass.isEmpty()) {
                        return true;
                    }
                    return false;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }).collect(Collectors.toList());
            // 如果同时存在 JAR 文件和 config 文件夹，返回 JAR 文件列表；否则返回空列表
            return jarPath;
        } catch (IOException e) {
            throw new RuntimeException("搜索文件时发生错误", e);
        }
    }

    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("需指定service目录与共享lib目录");
            return;
        }
        String servicePath = args[0];
        String shareJarPath = args[1];
        File shareJarPathFile = new File(shareJarPath);
        if (!shareJarPathFile.exists()) {
            System.out.println("共享jar包路径不存在");
            return;
        }


        List<Path> jarFiles = findJarFiles(servicePath);
        if (jarFiles == null || jarFiles.size() == 0) {
            System.out.println("未找到可执行Jar文件");
            return;
        }
        for (Path jarFile : jarFiles) {
            try {
                File libTargetDir = new File(jarFile.toFile().getParent()+File.separator+"lib");
                if (!libTargetDir.exists() && !libTargetDir.isDirectory()) {
                    libTargetDir.mkdir();
                }
                Set<String> dependencies = parseManifestDependencies(jarFile.toFile());

                if (dependencies == null || dependencies.isEmpty()) {
                    return;
                }
                int i = 0;
                for (String dependency : dependencies) {
                    if ("./conf/".equals(dependency)) {
                        continue;
                    }
                    if (dependency.startsWith("lib/")) {
                        dependency = dependency.substring(4);
                    }
                    if (dependency.startsWith("lib\\")) {
                        dependency = dependency.substring(4);
                    }
                    dependency = dependency.replace(";", "");
                    copy(jarFile.toFile().getAbsolutePath(),
                            shareJarPath + File.separator + dependency,
                            libTargetDir.getAbsolutePath() +File.separator + dependency);
                    i++;
                }
                System.out.println( "处理文件："+jarFile.toFile().getAbsolutePath()+"  依赖数量："+i);


            } catch (IOException e) {
                System.err.println("处理文件时发生错误：" + e.getMessage());
            }
        }

    }
}
